以先前範例比較 Kotlin & Flutter ListView
動態更新內容方式
修改以下四個檔案:
MainActivity.kt
activity_main.xml
colors.xml
MyAdapter.kt
實際執行完成畫面 |
---|
以下為 MainActivity.kt
檔案內容:
ViewModel
刷新 ListVeiw
資料。package com.example.kotlin_demo
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.AdapterView
import android.widget.Button
import android.widget.ListView
import android.widget.TextView
import androidx.core.content.ContextCompat
import kotlin.math.absoluteValue
import kotlin.random.Random
class MainActivity : AppCompatActivity() {
private val viewModel = MyViewModel()
private val bookData = mutableListOf<BookInfor>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val listView : ListView = findViewById<ListView>(R.id.listView)
for(bookNum in 1..9){
bookData.add(BookInfor("MyBook$bookNum","Author$bookNum","2023-09-0$bookNum"))
}
viewModel.addList(bookData)
val adapter = MyAdapter(this)
//當 viewModel.BookList 資料被更新時,重新設定 Adapter 資料
viewModel.BookList.observe(this,{
adapter.setData(it)
})
listView.adapter = adapter
val textView: TextView = findViewById<TextView>(R.id.TV);
listView.setOnItemClickListener(object:AdapterView.OnItemClickListener{
override fun onItemClick(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
textView.setText("${p0!!.adapter.getItem(p2)}")
}
})
///更新資料按鈕
val buttonForUpDateData: Button = findViewById<Button>(R.id.Button);
buttonForUpDateData.apply {
setText("Update ListView Data")
isAllCaps = false;
setBackgroundColor(ContextCompat.getColor(this.context, R.color.orangeAccent))
setTextColor(ContextCompat.getColor(this.context, R.color.white))
setOnClickListener(object : View.OnClickListener {
override fun onClick(p0: View?) {
///隨機取得20以下其中一個數字
var iInitialRandomNum: Int = Random.nextInt(20)
createSampleData(iInitialRandomNum, iInitialRandomNum + 9)
}
})
}
}
//建立範例資料
/// iInitialNum (初始值) , iMaxNum (最大值)
fun createSampleData(iInitialNum: Int = 1, iMaxNum: Int = 9) {
val list = mutableListOf<BookInfor>()
///依照 初始值與最大值 建立連續資料
for (bookNum in iInitialNum..iMaxNum) {
list.add(
BookInfor(
"MyBook$bookNum",
"Author$bookNum",
if (bookNum < 10) "2023-09-0$bookNum" else "2023-09-$bookNum"
)
)
}
///清除目前頁面 ListView 資料
bookData.clear()
///設定目前頁面 ListView 資料為新建的範例資料
bookData.addAll(list)
///更新ViewModel 的 BookList 書籍資料
viewModel.BookList.value = bookData
}
}
以下為 activity_main.xml
檔案內容:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="@+id/listView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button android:id = "@+id/Button"
android:layout_width="wrap_content"
android:layout_height="100dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/listView"
/>
<TextView
android:id = "@+id/TV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/Button"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
以下為 colors.xml
檔案內容:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="amber">#FFFFC107</color>
<color name="lightGreen">#FF8BC34A</color>
<color name="yellow">#FFFFEA00</color>
<color name="orangeAccent">#FFFFAB40</color>
</resources>
以下為 MyAdapter.kt
檔案內容:
Adapter
資料,再刷新資料。fun setData(itemList: List<BookInfor>) {
/// 清除資料
clear()
addAll(itemList)
notifyDataSetChanged()
}
main.dart
:
GestureDetector
元件監聽按鈕點擊事件。bookInfoList
變數。setState((){});
:由 新的bookInfoList
變數建立新的 ListView 元件。實際執行結果畫面 |
---|
import 'dart:math';
import 'package:flutter/material.dart';
import 'BookInfor.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<StatefulWidget> {
///設定文字大小
double dTextSize = 20;
///書籍資訊相關資料
List<BookInfor> bookInfoList = [];
//需顯示的元件
Widget? _wPrintedItem;
@override
void initState() {
super.initState();
setData();
}
@override
Widget build(BuildContext context) {
List<Widget> widgetList = [
Expanded(child: _wListView(),flex: 7,),
Expanded(child: _wUpdateDataButton()),
];
widgetList.add(Expanded(child: _wPrintedItem ?? Container(),flex: 2,));
//建立 ListView
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Column(
children: widgetList,
)));
}
///ListView 元件
Widget _wListView() {
return ListView(
//依 資料 List 長度並轉為 元件 List 資料結構
children: List.generate(bookInfoList.length , (index) => _wListItem(bookInfoList[index])),
);
}
///ListView item 元件
/// - [sNum] : 帶入的數字
Widget _wListItem(BookInfor data) {
//Column 元件將 child 元件由上到下垂直排列
return InkWell(
onTap: () {
setState(() {
_wPrintedItem = _wPrintTappedItem(data);
});
},
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
//Card 元件包著書籍資訊,
//注意 Card 元件預設有 margin, 需要設為0才會完全貼齊其他元件
Card(
margin: EdgeInsets.zero,
child: _wBookItem(data),
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(11)),
),
//分隔線
const Divider(
thickness: 1,
height: 0.5,
),
]));
}
///書籍 item 元件
/// - [sNum] : 需帶入的數字
Widget _wBookItem(BookInfor bookData) {
//Container 元件會依據 child 元件大小包覆,方便設定 child 元件的 padding 或 margin
return Container(
padding: EdgeInsets.symmetric(vertical: 5, horizontal: 5),
//Column 元件將 _wBookNameAuthor 和 _wBookBuyDate 元件由垂直排列
// MainAxisSize.min 設定代表 只依 child 元件大小包住 child 元件,不會延伸到最大螢幕畫面
// CrossAxisAlignment.start 設定代表 垂直靠左排列
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_wBookNameAuthor(bookData.sBookName, bookData.sBookAuthor),
_wBookBuyDate(bookData.sBookBuyDate),
],
));
}
///書籍名稱與作者 元件
/// - [sName] : 書籍名稱
/// - [sAuthor] : 書籍作者
Widget _wBookNameAuthor(String sName, String sAuthor) {
return Container(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
// 文字元件
Text(
sName,
style: TextStyle(fontSize: dTextSize),
),
Container(
width: 10,
),
Text(
sAuthor,
style: TextStyle(fontSize: dTextSize),
),
],
));
}
///書籍購買日期元件
/// - [sDate] : 購買日期
Widget _wBookBuyDate(String sDate) {
return Container(
child: Text(
sDate,
style: TextStyle(fontSize: dTextSize),
));
}
///設定 ListView 資料
setData() {
setSampleData();
}
///印出 ListView 被點擊的 Item 資料
Widget _wPrintTappedItem(dynamic Data) {
return Container(child: Text("$Data"));
}
/// 更新資料按鈕元件
Widget _wUpdateDataButton(){
///初始化隨機數字
int iIntialRandomNum = Random().nextInt(20).abs();
return GestureDetector(
onTap: () {
setSampleData(iInitialNum: iIntialRandomNum, iMaxNum: iIntialRandomNum + 10);
setState(() {});
},
child: Container(
alignment: Alignment.center,
constraints: BoxConstraints(maxWidth: 150),
decoration: BoxDecoration(
color: Colors.orangeAccent,
borderRadius: BorderRadius.circular(15)),
child: Text(
"Update ListView Data",
style: TextStyle(color: Colors.white,),
textAlign: TextAlign.center
),
),
);
}
/// 建立範例資料
/// - 由起始數值和結束數值決定範例資料
/// - [iInitialNum] : 起始數值
/// - [iMaxNum] : 結束數值
setSampleData({int iInitialNum = 1, int iMaxNum = 10}) {
List<BookInfor> list = [];
if (list.isEmpty) {
for (int i = iInitialNum; i < iMaxNum; i++) {
list.add(BookInfor("MyBook$i", "Author$i", i < 10 ? "2023-09-0$i" : "2023-09-$i"));
}
bookInfoList.clear();
bookInfoList.addAll(list);
}
}
}
ListView
資料方式Kotlin | Flutter | |
---|---|---|
如何動態更新 ListView 資料 |
observer callback 刷新 ListView Adapter 資料 |
更新 ListView 資料來源變數內容,並 setState((){}); 生成新 ListView 元件 |